#ifndef OS_SCHED_H
#define OS_SCHED_H

#include "os_cfg.h"
#include "os_plat.h"
#include "os_list.h"
#include "os_task.h"
#include "os_mem.h"

/**
 * 内核核心数据结构
 * 不放在头文件，不然会有很多文件包含方面的问题
 */
typedef struct _os_core_t {    
    os_task_t * curr_task;                      // 当前正在运行的任务
    os_task_t * next_task;                      // 下一要运行的任务

    // 优先级位图
    uint8_t ready_group;                            // 优先级组位图
	uint8_t ready_map[8];                           // 各分组位图
    os_list_t ready_list[OS_TASK_PRIO_MAX + 1];     // 优先级就绪列表

    os_task_t idle_task;                        // 优先级任务
#if OS_TIMER_ENABLE
    os_task_t timer_task;                       // 定时器任务
#endif
    os_list_t all_list;                         // 所有任务
    os_list_t delay_list;                       // 延时队列
#if OS_TASK_DEL_ENABLE
    os_list_t delete_list;                      // 待删除的任务队列
#endif
#if OS_TASK_SUSPEND_ENABLE || OS_TASK_SCHED_CHECK_STACK
    os_list_t pend_list;                        // 挂起队列，放置所有挂起的任务
#endif
#if OS_SCHED_LOCK_ENABLE
    uint8_t sched_locked;                       // 调度锁锁定的计数值
#endif
    uint8_t int_nested;                         // 中断嵌套次数
    uint8_t sched_from_int;                     // 是否从中断中进行任务切换
    os_ticks_t startup_ticks;                   // 时钟节拍计数值

    os_mem_t free_list;                         // 空闲内存块链表
}os_core_t;

extern os_core_t os_core;

void os_sched_init (void);
void os_sched_run (void);
void os_sched_lock (void);
void os_sched_unlock (void);

void os_sched_set_ready (os_task_t * task);
void os_sched_remove_ready (os_task_t * task);
void os_sched_set_delay (os_task_t * task, int ms);
void os_sched_remove_delay (os_task_t * task);
void os_sched_set_suspend (os_task_t * task);
void os_sched_remove_suspend (os_task_t * task);
void os_sched_set_deleted(os_task_t * task);
os_task_t * os_sched_remove_deleted (void);

void os_sched_add_new (os_task_t * task);
void os_sched_remove (os_task_t * task);

void os_sched_time_tick (void);
os_task_t * os_task_self (void);
os_ticks_t os_tick_count(void);

os_task_ctx_t *os_sched_switch_ctx(os_task_ctx_t *ctx);
void os_task_switch_to (os_task_ctx_t * to);
void os_task_switch(os_task_ctx_t * from, os_task_ctx_t *to);
void os_int_switch (os_task_ctx_t * from, os_task_ctx_t * to);
void os_task_ctx_init(os_task_t *task, void * stack_start, int stack_size, void (*entry)(void *), void *param);

void os_sched_yield (void);

void os_sched_run_first (void);

os_int_status_t os_sched_int_lock(void);
void os_sched_int_restore(os_int_status_t status);

void os_int_enter (void);
void os_int_leave (void);

void os_task_switch_hook(os_task_t * from, os_task_t * to);
void os_systick_hook (void);

#endif // OS_CORE_H
